home *** CD-ROM | disk | FTP | other *** search
- /*
- FILE: sintab.c
- PROJECT: Ford grant DSP
- AUTHOR: Ben Denckla
- COMMENT: sine table generation & lookup
- */
-
- #include "aiff.h"
- #include "sintab.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h> // must come before SANE #include to have precedence
- #include <SANE.h>
-
- #define HALFPI 1.5707963 // half of pi
- #define SINAMP 0x7FFF // sine wave amplitude
-
- short sintab[QSIZ+1];
-
- DEFFUNC( double round( double x )) {
- double offset = 0.5;
- if( x < 0.0 ) offset = -offset;
- return x + offset;
- }
-
- // puts a 1st-quadrant sine table into sintab[]
- void get_sintab ( void ) {
- short i;
- double rads;
-
- sintab[0] = 0;
- sintab[QSIZ] = SINAMP;
- for (i=1; i < QSIZ; i++)
- sintab[i] = round( SINAMP * sin( HALFPI * i / QSIZ ) );
- }
- /*
- 1. Small enough means that the correct last value is found where expected.
- 2. Does not deserve a call to exit because a file error here does not impede
- function of program and therefore is not a fatal error.
- */
-
- // puts a full 4-quadrant sine table into sintab4[] using sintab()
- short *gen_sintab4 ( void ) {
- unsigned short i;
- short *sintab4, *tsintab4;
-
- if (!(sintab4 = malloc( 2L*4*QSIZ )))
- err( "Could not allocate 4-quadrant sine table memory" );
-
- tsintab4 = sintab4;
- for (i=0; i<4*QSIZ; i++)
- *tsintab4++ = sin_tab( i );
- return sintab4;
- }
-
- // returns SINAMP * sin (pi/2 * tabi/QSIZ) using sintab[]
- // tabi is assumed to be non-negative
- short sin_tab( short tabi ) {
- register short i;
-
- i = tabi & (2*QSIZ-1); // i = tabi % 2QSIZ;
- if ( i & QSIZ ) // if ( i >= QSIZ )
- i = 2*QSIZ - i; // reflect i from the 2nd to the 1st quadrant
- if ( tabi & (2*QSIZ) ) // if ( (tabi % 4QSIZ) >= 2QSIZ )
- return -sintab[i]; // negate sintab[i] if in 3rd or 4th quadrant
- else return sintab[i];
- }
-
- // getusrharm() asks the user for a frequency and returns number of the
- // closest harmonic of the sine table frequency
- short getusrharm() {
- double infreq, oufreq, tabfreq, centerr;
- short retval;
-
- GETNUMRANGE( "frequency", "%.1lf", "%lf", infreq, 0.0, ph.rate/2 );
-
- tabfreq = ph.rate / (4*QSIZ); // sine table frequency (1)
- retval = infreq / tabfreq + 0.5; // (2)
- if (!retval) retval++; // bump 0th harmonic up to 1st
- oufreq = tabfreq * retval; // output frequency
- if (oufreq > ph.rate/2) { // if Nyquist freq. exceeded
- oufreq -= tabfreq; // bump oufreq down 1 harmonic
- retval--; // bump retval down 1 harmonic
- }
- centerr = 1200 * log( oufreq/infreq ) / log(2); // 3
- printf( "\tUsing %.3f Hz, %.3f Hz or %.1f cents away\n\n",
- oufreq, oufreq - infreq, centerr );
- return retval;
- }
- /*
- 1. sine table frequency >= 1 Hz ==> 4*QSIZ <= 44100 < 0x10000 ==> 4*QSIZ
- fits in an unsigned word.
- 2. harmonic of tabfreq closest to infreq (+ 0.5 rounds).
- 3. cent error is the interval between oufreq and infreq
- */